package com.example.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.service.IOAWorkflowService;
import com.example.util.CacheTokenUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.HtmlUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.IntStream;

/**
 * @创建人 liangzai
 * @创建时间 2022/10/21
 * @描述 流程接口业务层
 */
@Slf4j
@Service
public class OAWorkflowServiceImpl implements IOAWorkflowService {
     private static  final  String  oaUrl = "http://127.0.0.1:8899";


    /**
     * 获取 OA接口的token
     *
     * @param userName 用户名
     * @param password 密码
     */
    @Override
    public String getToke(String userName, String password) {
         //jsonObject.put("userName", "rest");
        //jsonObject.put("password", "jsgl_oa123456");
        Assert.isTrue(StrUtil.isNotBlank(userName), "用户名不能为空");
        Assert.isTrue(StrUtil.isNotBlank(password), "密码不能为空");
        String url = oaUrl + "/seeyon/rest/getToke";
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("userName", userName);
        jsonObject.put("password", password);
        log.info("【获取OA接口的token，请求RUL={}， 请求参数 :{}】", url, jsonObject);
        //String result= HttpUtil.createPost(url).header("Content-Type", "application/json").form(jsonObject).execute().body();
        String result = HttpUtil.createPost(url).contentType("application/json").body(JSONObject.toJSONString(jsonObject)).execute().body();


        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-type", "application/json; charset=utf-8");
        headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
        headers.add("Accept", "application/json;charset=UTF-8");
        MultiValueMap<String, String> mapsData = new LinkedMultiValueMap<>();
        HttpEntity<Object> requestEntity = new HttpEntity<>(mapsData, headers);
        // Map response = restTemplate.getForObject(url, Map.class);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<Map> result12 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);
        Map map = result12.getBody();
        //String result = HttpUtil.post(url, jsonObject);
        log.info("【获取OA接口的token，返回结果 :{}】", result);
        //成功： {"id": "013a2a1e-a0b0-4f66-b533-da0563f89c6c"}  失败：{"id": "-1"}
        if (StrUtil.isBlank(map.toString())) {
            throw new RuntimeException("【获取OA接口的token接口返回为空异常】");
        }
        JSONObject object = JSONObject.parseObject(result);
        String token = object.getString("id");
        CacheTokenUtil.add("token", token);
        if (Objects.equals("-1", token)) {
            throw new RuntimeException("【获取OA接口的token接口失败】");
        }
        return token;
    }

    public static void main(String[] args) {
        String test ="<p>消息提醒消息消息提醒</p><p><br></p>";
        String aa ="消息提醒";
        //String s = HtmlUtils.htmlEscape(aa);
        //System.out.printf("s=======" +s );
        String encode = null;
        try {
            encode = URLEncoder.encode(test, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println("encode:" + encode);

        String testEncode = null;
        try {
            testEncode = URLEncoder.encode(test, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println("testEncode:" + testEncode);



    }
    /**
     * OA文件上传接口，支持多文件
     *
     * @param files 文件
     * @param
     */
    @SneakyThrows
    @Override
    public List<HashMap<String, Object>> uploadFiles(List<MultipartFile> files) {
        //获取token
        String token = "123";
        /*token = CacheTokenUtil.get("token");
        if (StrUtil.isBlank(token)) {
            token = getToke("rest", "jsgl_oa123456");
        }*/
        log.info("【token ={}】", token);
        String url = oaUrl + "/seeyon/rest/attachment?token=" + token;

        RestTemplate restTemplate = new RestTemplate();
        MultiValueMap<String, Object> multipartRequest = new LinkedMultiValueMap<>();
        for (MultipartFile multipartFile : files) {
            ByteArrayResource fileAsResource = new ByteArrayResource(multipartFile.getBytes()) {
                @Override
                public String getFilename() {
                    return multipartFile.getOriginalFilename();
                }
                @Override
                public long contentLength() {
                    return multipartFile.getSize();
                }
            };
            multipartRequest.add("files", fileAsResource);
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        multipartRequest.add("token",token);
        HttpEntity<MultiValueMap<String, Object>> body = new HttpEntity(multipartRequest, headers);
        log.info("【OA文件上传接口，请求RUL={}， 请求参数 :{}】", url, body);
        JSONObject jsonObject = restTemplate.postForObject(url, body, JSONObject.class);
        log.info("【OA文件上传接口，返回结果 ={}】", jsonObject);
        if (null == jsonObject) {
            throw new RuntimeException("【OA文件上传接口返回为空异常】");
        }
        List<HashMap<String, Object>> upFileParams = new ArrayList<>();
        JSONArray atts = jsonObject.getJSONArray("atts");
        if (CollUtil.isEmpty(atts)) {
            return upFileParams;
        }
        IntStream.range(0, atts.size()).forEach(i -> {
            HashMap<String, Object> map = new HashMap<>();
            JSONObject jsonObject1 = atts.getJSONObject(i);
            if (null != jsonObject1) {
                map.put("subReference", jsonObject1.getString("subReference"));
                map.put("fileUrl", jsonObject1.getString("fileUrl"));
                map.put("sort", jsonObject1.getString("sort"));
                upFileParams.add(map);
            }
        });
        return upFileParams;
    }


    /**
     * 发起流程审批
     *
     * @param params 页面流程审批Map请求参数
     * @return 流程单编号
     */
    @Override
    public String startFlow(Map<String, Object> params,List<MultipartFile> files) {
        log.info("【发起流程审批， 页面请求参数={}】", JSON.toJSONString(params));
        Assert.isTrue(MapUtil.isNotEmpty(params), "发起流程审批入参不能为空");
        String url = oaUrl + "/seeyon/rest/bpm/process/start";
        Map<String, Object> map = new HashMap<>();
        //应用类型
        map.put("appName", "collaboration");
        Map<String, Object> dataOne = new HashMap<>(16);
        //模板编号
        dataOne.put("templateCode", "SJKCXDJ");
        //是否为待发 0:新建-发送；1:新建-保存待发
        dataOne.put("draft", "0");
        dataOne.put("attachments", new ArrayList<Long>());
        Map<String, Object> dataTwo = new HashMap<>(16);
        //上传文件的返回参数
        //List<MultipartFile> files = (List<MultipartFile>) params.get("files");
       //List<HashMap<String, Object>> hashMaps = uploadFiles(files);
        List<HashMap<String, Object>> hashMaps = new ArrayList<>();
        HashMap<String, Object> map1 =  new HashMap<>(16);
        map1.put("subReference", "123456");
        map1.put("fileUrl", "123456");
        map1.put("sort", 0);
        hashMaps.add(map1);
        //附件参数
        dataTwo.put("thirdAttachments", hashMaps);
        dataTwo.put("formmain_14610", new HashMap<String, Object>() {{
            //申请日期  申请部门 经办人 申请事项 申请理由
            put("field0001", params.get("applyTime"));
            put("field0003", params.get("applyOrgName"));
            put("field0002", params.get("operName"));
            put("field0011", params.get("applyThings"));
            put("field0017", params.get("applyReason"));
            put("field0010", hashMaps.get(0).isEmpty() ? "" : hashMaps.get(0).get("subReference"));
        }});
        dataOne.put("data", dataTwo);
        map.put("data", dataOne);
        log.info("【发起流程审批， 请求地址={}，请求参数={}】", url, JSON.toJSONString(map));
        String result = HttpUtil.post(url, map);
        log.info("【发起流程审批， 响应结果={}】", JSON.toJSONString(result));
        if (StrUtil.isBlank(result)) {
            throw new RuntimeException("【发起流程审批接口返回结果为空异常】");
        }
        JSONObject jsonObject = JSON.parseObject(result);
        JSONObject data = jsonObject.getJSONObject("data");
        if (data != null) {
            String processId = data.getString("processId");
            log.info("【发起流程审批， 返回流程ID={}】", processId);
            return processId;
        }
        return null;
    }


    /**
     * 查询流程单处理状态
     *
     * @param workflowCode 流程单编号
     * @return 流程状态 状态 0-通过 1-不通过 2-审批中
     */
    @Override
    public int checkFlowStatus(String workflowCode) {
        Assert.isTrue(StrUtil.isNotBlank(workflowCode), "流程编号不能为空");
        String url = "http://127.0.0.1:8117/seeyon/rest/flow/state/" + workflowCode;
        log.info("【查询流程单处理状态，请求流程编号 :{}】", workflowCode);
        String result = HttpUtil.get(url);
        log.info("【查询流程单处理状态，返回结果 :{}】", result);
        if (StrUtil.isBlank(result)) {
            throw new RuntimeException("【查询流程单处理状态接口异常】");
        }
        int status = Integer.parseInt(result);
        if (0 == status) {
            return 0;
        }
        if (5 == status || 15 == status) {
            return 1;
        }
        if(3 == status || 4 == status || 6 == status || 7 == status) {
            return 2;
        }
        return status;
    }
}
